

#ifdef __Win32__
        #pragma warning(disable:4786)
#endif
#include "../../MediaSource/ParserMgr.h"
#include "RmParser.h"
#include "RmReader.h"
#include "RmMediaSource.h"
#include "SSMonitorItems.h"

CRmMediaSource::CRmMediaSource( string filename ): CMediaSource1( filename )
{
        rmParser = NULL;
        rmReader = NULL;

		STAT_COUNT_INC(this);
}

CRmMediaSource::~CRmMediaSource(void)
{
        if ( rmReader )
        {
                delete rmReader;
                rmReader = NULL;
        }

        if (rmParser)
        {
                g_ParserMgr->FreeParser(rmParser->filename.c_str());
                rmParser = NULL;
        }

		STAT_COUNT_DEC(this);
}

Bool    CRmMediaSource::Initialize() {

        if (NULL == g_ParserMgr)
        {
                g_ParserMgr = ParserMgr::GetInstance();
        }
        rmParser = (RmParser *)g_ParserMgr->GetParser( filename.c_str() );

        if ( !rmParser ) return FALSE;

        rmReader = new RmReader();
        if ( !rmReader ) return FALSE;

        return rmReader->Initialize( filename );
}

string CRmMediaSource::GetSDP() {
 	OutputDebugStringA("CMediaAdapter::Setup CMediaTransport::GetSDP CRmMediaSource::GetSDP");
       return rmParser->GetSDP();
}

SLOT_TABLE *  CRmMediaSource::GetLengthTable()
{
        return rmParser->GetLengthTable();
}


UInt32                  CRmMediaSource::GetNumOfIndex()
{
        return rmParser->GetNumOfIndex();
}

UInt16                  CRmMediaSource::GetAudioNumber()
{
        return rmParser->GetAudioNumber();
}

UInt16                  CRmMediaSource::GetVideoNumber()
{
        return rmParser->GetVideoNumber();
}

UInt32                  CRmMediaSource::GetAudioBitrate()
{
        return rmParser->GetAudioBitrate();
}

UInt32                  CRmMediaSource::GetVideoBitrate()
{
        return rmParser->GetVideoBitrate();
}

UInt32                  CRmMediaSource::GetBitrate()
{
        return rmParser->GetBitrate();
}

CDataPacket * CRmMediaSource::GetNextDataPacket()
{
        rmff_frame_t * frame = NULL;
        frame = rmReader->ReadNextFrame() ;
        if (frame == NULL)   return NULL;

        CDataPacket * packet = CDataPacket::CreatePacket( frame );

        rmReader->ReleaseFrame( frame );

        return packet ;
}

CTimeSlot * CRmMediaSource::GetTimeSlot( UInt32 second ) {

        if (second >= rmParser->GetNumOfIndex()) return NULL;

        CTimeSlot * pSlot = new CTimeSlot( second );

        if ( !pSlot ) return NULL;

        UInt32  packetCounts = rmParser->GetPacketCounts( second );                     

        UInt32 offset = rmParser->GetOffset( second );                                              
        rmReader->Seek( offset );

        for ( Int32 i = 0; i < packetCounts; i++)
        {
                CDataPacket * pPacket = GetNextDataPacket();
                if (pPacket != NULL)
                        pSlot->PutDataPacket( pPacket );
        }

        return pSlot;                                                                           

}

Int32   CRmMediaSource::SeekBySliceNum(UInt32& nSliceNum)
{
        do
        {
                if (nSliceNum >= rmParser->GetNumOfIndex()) return -1;
                UInt32 offset = rmParser->GetOffset( nSliceNum );                                               
                if (offset>0)
                {
                        if (rmReader->Seek( offset ))
                        {
                                return 0;
                        }
                }
                //printf("failed to seek;index:%d,offset:%d,try to seek:%d\n",nSliceNum,offset,nSliceNum+1);
        } while (false);
        return -2;
}

CTimeSlot* CRmMediaSource::ReadTimeSlotByDuration(UInt32 nSliceNum,UInt32 nBeginStamp,UInt32 nEndStamp)
{
        CTimeSlot * pSlot = new CTimeSlot( nSliceNum );
        if ( !pSlot ) return NULL;
	const UInt32 audio_id = 0;
	const UInt32 video_id = 1;
	UInt32 trackid = 0;
        UInt16 num_total_audio =        rmParser->GetPacketsCountBefore(nSliceNum,audio_id);
        UInt16 num_total_video =        rmParser->GetPacketsCountBefore(nSliceNum,video_id);
        UInt16 na=0,nv=0;
	Bool	audio_ok = FALSE;
	Bool	video_ok = FALSE;
        Bool bOK = FALSE;
	UInt32	ts;
        for (;;)
        {
                CDataPacket * pPacket = GetNextDataPacket();
                if (pPacket != NULL)
                {
			ts = pPacket->GetTimeStamp();
			trackid = pPacket->GetChanID();
			if( ts < nBeginStamp)
			{
				delete pPacket;
				continue;
			}
			else if( ts >= nEndStamp)
			{
				if(trackid == audio_id)
					audio_ok = TRUE;
				else
					video_ok = TRUE;

				delete pPacket;

				//all stream data are ok
				if(audio_ok && video_ok)
					break;

				continue;
			}
			else
			{
				if (trackid == audio_id)
				{
					pPacket->SetSeqNum(num_total_audio+na);
					na++;
				} else if (trackid == video_id)
				{
					pPacket->SetSeqNum(num_total_video+nv);
					nv++;
				}
			}

//			printf("get track:%d, data timestamp:%d\n",trackid, ts);
						
                        pSlot->PutDataPacket( pPacket );
                }
                else
                        break;
        }

//	printf("[PARA]Index:%d,Offset:%d,Start:%d,End:%d;[DATA]First T:%d,End T:%d,LEN:%d\n",nSliceNum,rmParser->GetOffset( nSliceNum ),nBeginStamp,nEndStamp,b,e,len);
        return pSlot;                                                                           
}

CTimeSlot* CRmMediaSource::GetTimeSlotByDuration(UInt32 nSliceNum,UInt32 nBeginStamp,UInt32 nEndStamp)
{
        UInt32 ns1 = nEndStamp/TIMESCALE;
        for (UInt32 i=0; i<=ns1-nSliceNum; i++)
        {
                UInt32 nSN = nSliceNum + i;
                Int32 iRet = SeekBySliceNum(nSN);
                if (iRet==0)
                {
                        return ReadTimeSlotByDuration(nSN,nBeginStamp,nEndStamp);
                }
                if (iRet == -1) break;
        }
        return NULL ;
        //if(SeekBySliceNum(nSliceNum)<0) return NULL;
        //return ReadTimeSlotByDuration(nSliceNum,nBeginStamp,nEndStamp);
}

UInt32 CRmMediaSource::GetDuration()
{
        return rmParser->GetDuration(); 
}

UInt32 CRmMediaSource::GetSecondNum()
{
        return rmParser->GetSecondNum();
}

